/*
 *
 *  * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 *
 *
 */

package com.iwindplus.binlog.comsumer.server.handler;

import com.iwindplus.base.alert.service.AlertFeishuService;
import com.iwindplus.base.domain.enums.DbActionTypeEnum;
import com.iwindplus.base.util.JacksonUtil;
import com.iwindplus.binlog.comsumer.server.domain.dto.BinlogActionCheckSignDTO;
import com.iwindplus.binlog.comsumer.server.domain.dto.BinlogActionProcessDTO;
import com.iwindplus.binlog.comsumer.server.domain.dto.BinlogRowDataDTO;
import com.iwindplus.binlog.comsumer.server.domain.dto.SourceMetaDTO;
import com.iwindplus.binlog.comsumer.server.domain.property.BinLogConsumerProperty;
import com.iwindplus.binlog.comsumer.server.domain.property.BinLogConsumerProperty.Webhook;
import com.iwindplus.binlog.comsumer.server.strategy.context.BinlogActionStrategyContext;
import com.iwindplus.log.client.BinlogAlertClient;
import com.iwindplus.log.domain.dto.BinlogAlertDTO;
import com.lark.oapi.service.im.v1.enums.MsgTypeEnum;
import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * binlog 处理助手.
 *
 * @author zengdegui
 * @since 2025/11/30 00:23
 */
@Slf4j
@Component
public class BinlogActionHandler {

    @Resource
    protected BinLogConsumerProperty property;

    @Value("${spring.profiles.active}")
    private String env;

    @Resource
    private BinlogActionStrategyContext<BinlogRowDataDTO, BinlogActionCheckSignDTO> binlogActionStrategyContext;

    @Resource
    private AlertFeishuService alertFeishuService;

    @Resource
    private BinlogAlertClient binlogAlertClient;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 处理binlog数据.
     *
     * @param entity binlog数据
     */
    public void processHandler(BinlogRowDataDTO entity) {
        // 验签
        final DbActionTypeEnum actionType = DbActionTypeEnum.fromAlias(entity.getOp());
        BinlogActionProcessDTO<BinlogRowDataDTO> processDTO = BinlogActionProcessDTO
            .<BinlogRowDataDTO>builder()
            .actionType(actionType)
            .data(entity)
            .build();
        final BinlogActionCheckSignDTO checkSignDTO = this.binlogActionStrategyContext.execute(processDTO);
        if (Objects.nonNull(checkSignDTO) && Boolean.TRUE.equals(checkSignDTO.getSuccess())) {
            return;
        }

        // todo 处置

        final SourceMetaDTO source = entity.getSource();
        final BinlogAlertDTO binlogAlertDTO = BinlogAlertDTO.builder()
            .tsMs(entity.getTsMs())
            .db(source.getDb())
            .table(source.getTable())
            .dataId(entity.getDataId())
            .file(source.getFile())
            .pos(source.getPos())
            .actionType(actionType)
            .before(JacksonUtil.toJsonStr(entity.getBefore()))
            .after(JacksonUtil.toJsonStr(entity.getAfter()))
            .message(checkSignDTO.getMessage())
            .build();
        this.threadPoolTaskExecutor.submit(() -> this.binlogAlertClient.save(binlogAlertDTO));
        this.threadPoolTaskExecutor.submit(() -> this.sendMsg(entity, actionType, checkSignDTO.getMessage()));
    }

    private boolean sendMsg(BinlogRowDataDTO dto, DbActionTypeEnum actionType, String message) {
        final Webhook webhook = property.getWebhook();
        if (Boolean.FALSE.equals(webhook.getEnabled())) {
            return false;
        }

        final SourceMetaDTO source = dto.getSource();

        final String data = new StringBuilder("数据库表数据被篡改").append("\n\n")
            .append("环境：").append(env).append("\n")
            .append("库名：").append(source.getDb()).append("\n")
            .append("表名：").append(source.getTable()).append("\n")
            .append("操作：").append(actionType.name()).append("\n")
            .append("操作前主键：").append(dto.getBeforeId()).append("\n")
            .append("操作前加签盐：").append(dto.getBeforeSalt()).append("\n")
            .append("操作后主键：").append(dto.getAfterId()).append("\n")
            .append("操作后加签盐：").append(dto.getAfterSalt()).append("\n")
            .append("原因：").append(message).append("\n").toString();

        final Map<Object, Object> map = new HashMap<>(16);
        map.put(MsgTypeEnum.MSG_TYPE_TEXT.getValue(), data);
        String content = JacksonUtil.toJsonStr(map);
        // return alertFeishuService.sendAlertMsg("2f13ge3a",  content);
        return alertFeishuService.sendWebhookMsg(webhook.getUrl(), MsgTypeEnum.MSG_TYPE_TEXT, content, webhook.getSecret());
    }

}
